/*
 * @Copyright: 2024 Qujunyang
 * @Author: QuJunyang
 * @Date: 2024-01-25 18:12:34
 * @LastEditTime: 2024-02-01 14:16:17
 * @LastEditors: QuJunyang
 * @FilePath: \learn_av\tutorial1-pcm\src\main.rs
 * @Description: 
 */
use std::fs::File;
use std::io::{self, Read, Result, Write};
use std::env;

#[allow(dead_code)]
fn simplest_pcm16le_split(pcm_file: &str) -> io::Result<()> {
    // print args
    let mut pcm_handle = File::open(pcm_file)?;

    let left_pcm_file = "./left.pcm";
    let right_pcm_file = "./right.pcm";
    
    let mut left_pcm_handle = File::create(left_pcm_file)?;
    let mut right_pcm_handle = File::create(right_pcm_file)?;

    // 假设 pcm 文件为 16bit 小端存储
    let mut buffer = [0u8; 4];

    while pcm_handle.read_exact(&mut buffer).is_ok() {
        let left_sample = i16::from_le_bytes([buffer[0], buffer[1]]);
        let right_sample = i16::from_le_bytes([buffer[2], buffer[3]]);

        left_pcm_handle.write_all(&left_sample.to_le_bytes()).expect("failed to write left channel.");
        right_pcm_handle.write_all(&right_sample.to_le_bytes()).expect("failed to write right channel.");
    }

    Ok(())
}

#[allow(dead_code)]
fn simplest_pcm16le_halfvolumeleft(audio_file: &str) -> io::Result<()> {
    let mut audio_handle = File::open(audio_file)?;
    let output = "./halfvolumeleft.pcm";
    let mut output_halfvolumeleft_handle = File::create(output)?;

    let mut buffer = [0u8; 4];

    while audio_handle.read_exact(&mut buffer).is_ok() {
        let mut left_sample = i16::from_le_bytes([buffer[0], buffer[1]]);
        left_sample /= 2;
        let right_sample = i16::from_le_bytes([buffer[2], buffer[3]]);

        output_halfvolumeleft_handle.write_all(&left_sample.to_le_bytes()).expect("failed to write left sample to ./halfvolumleft.pcm");
        output_halfvolumeleft_handle.write_all(&right_sample.to_le_bytes()).expect("failed to write left sample to ./halfvolumleft.pcm");
    }


    Ok(())
}

#[allow(dead_code)]
fn simplest_pcm16le_doublespeed(audio_file: &str) -> io::Result<()> {
    let mut audio_handle = File::open(audio_file)?;
    let output = "./doublespeed.pcm";
    let mut output_doublespeed_handle = File::create(output)?;

    let mut count: u32 = 0;

    let mut buffer = [0u8; 4];

    while audio_handle.read_exact(&mut buffer).is_ok() {
        let left_sample = i16::from_le_bytes([buffer[0], buffer[1]]);
        let right_sample = i16::from_le_bytes([buffer[2], buffer[3]]);

        if count % 2 == 0 {
            output_doublespeed_handle.write_all(&left_sample.to_le_bytes()).unwrap();
            output_doublespeed_handle.write_all(&right_sample.to_le_bytes()).unwrap();
        }
        count += 1;
    }

    Ok(())
}

#[allow(dead_code)]
fn simplest_pcm16le2pcm8(audio_file: &str) -> io::Result<()> {
    let mut audio_handle = File::open(audio_file)?;
    let output = "./output_pcm8.pcm";
    let mut output_pcm8_handle = File::create(output)?;

    let mut buffer = [0u8; 4];

    while audio_handle.read_exact(&mut buffer).is_ok() {
        let left_sample = i16::from_le_bytes([buffer[0], buffer[1]]);
        let right_sample = i16::from_le_bytes([buffer[2], buffer[3]]);

        let left_sample_i8 = (left_sample >> 8) as i8;
        let right_sample_u8 = right_sample ;

        output_pcm8_handle.write_all(&left_sample_u8.to_le_bytes()).unwrap();
        output_pcm8_handle.write_all(&right_sample_u8.to_le_bytes()).unwrap();
    }
    Ok(())
}

fn main() -> std::io::Result<()> {
    let args: Vec<String> = env::args().collect();
    println!("all args: {:?}", args);
    assert_eq!(args.len(), 2);
    let pcm_file = &args[1];

    // simplest_pcm16le_split(pcm_file)?;
    // simplest_pcm16le_halfvolumeleft(pcm_file)?;
    simplest_pcm16le2pcm8(pcm_file)?;
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_pcm16le_split() {
        let rs = simplest_pcm16le_split("D:/ws/xdo/learn_av/asset/test.pcm");
        assert!(rs.is_ok());
    }

    #[test]
    fn test_pcm16le_halfvolumeleft() {
        let rs = simplest_pcm16le_halfvolumeleft("D:/ws/xdo/learn_av/asset/test.pcm");
        assert!(rs.is_ok());
    }

    #[test]
    fn test_pcm16le_doublespeed() {
        let rs = simplest_pcm16le_doublespeed("D:/ws/xdo/learn_av/asset/test.pcm");
        assert!(rs.is_ok());
    }

    #[test]
    fn test_pcm16le2pcm8() {
        let rs = simplest_pcm16le2pcm8("D:/ws/xdo/learn_av/asset/test.pcm");
        assert!(rs.is_ok());
    }
}
